home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / misc / gs261src.zip / iutil.c < prev    next >
C/C++ Source or Header  |  1993-05-13  |  12KB  |  421 lines

  1. /* Copyright (C) 1989, 1992, 1993 Aladdin Enterprises.  All rights reserved.
  2.  
  3. This file is part of Ghostscript.
  4.  
  5. Ghostscript is distributed in the hope that it will be useful, but
  6. WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  7. to anyone for the consequences of using it or for whether it serves any
  8. particular purpose or works at all, unless he says so in writing.  Refer
  9. to the Ghostscript General Public License for full details.
  10.  
  11. Everyone is granted permission to copy, modify and redistribute
  12. Ghostscript, but only under the conditions described in the Ghostscript
  13. General Public License.  A copy of this license is supposed to have been
  14. given to you along with Ghostscript so you can know your rights and
  15. responsibilities.  It should be in a file named COPYING.  Among other
  16. things, the copyright notice and this notice must be preserved on all
  17. copies.  */
  18.  
  19. /* iutil.c */
  20. /* Utilities for Ghostscript interpreter */
  21. #include "memory_.h"
  22. #include "string_.h"
  23. #include "ghost.h"
  24. #include "errors.h"
  25. #include "alloc.h"
  26. #include "dict.h"
  27. #include "iname.h"
  28. #include "iutil.h"            /* for checking prototypes */
  29. #include "ivmspace.h"            /* for refs_check_global */
  30. #include "ostack.h"            /* for opdef.h */
  31. #include "opdef.h"            /* for obj_cvs */
  32. #include "packed.h"            /* for array_get */
  33. #include "store.h"
  34. #include "gsmatrix.h"
  35. #include "gxdevice.h"            /* for gx_color_index */
  36. #include "gzcolor.h"
  37.  
  38. /* ------ Object utilities ------ */
  39.  
  40. /* Copy refs from one place to another. */
  41. int
  42. refcpy_to_old(ref *aref, uint index, register const ref *from,
  43.   register uint size, const char *cname)
  44. {    register ref *to = aref->value.refs + index;
  45.     if ( r_is_global(aref) )
  46.     {    int code = refs_check_global(from, size);
  47.         if ( code < 0 )
  48.             return code;
  49.     }
  50.     while ( size-- )
  51.         ref_assign_old(to, from, cname), to++, from++;
  52.     return 0;
  53. }
  54. void
  55. refcpy_to_new(register ref *to, register const ref *from, register uint size)
  56. {    while ( size-- )
  57.         ref_assign_new(to, from), to++, from++;
  58. }
  59.  
  60. /* Fill a new object with nulls. */
  61. void
  62. refset_null(register ref *to, register uint size)
  63. {    while ( size-- ) make_null_new(to), to++;
  64. }
  65.  
  66. /* Compare two objects for equality.  Return 1 if equal, 0 if not. */
  67. int
  68. obj_eq(register const ref *pref1, register const ref *pref2)
  69. {    ref nref;
  70.     if ( r_type(pref1) != r_type(pref2) )
  71.        {    /* Only a few cases need be considered here: */
  72.         /* integer/real (and vice versa), name/string */
  73.         /* (and vice versa), and extended operators. */
  74.         switch ( r_type(pref1) )
  75.            {
  76.         case t_integer:
  77.             return (r_has_type(pref2, t_real) &&
  78.                 pref2->value.realval == pref1->value.intval);
  79.         case t_real:
  80.             return (r_has_type(pref2, t_integer) &&
  81.                 pref2->value.intval == pref1->value.realval);
  82.         case t_name:
  83.             if ( !r_has_type(pref2, t_string) )
  84.                 return 0;
  85.             name_string_ref(pref1, &nref);
  86.             pref1 = &nref;
  87.             break;
  88.         case t_string:
  89.             if ( !r_has_type(pref2, t_name) )
  90.                 return 0;
  91.             name_string_ref(pref2, &nref);
  92.             pref2 = &nref;
  93.             break;
  94.         default:
  95.             if ( r_btype(pref1) != r_btype(pref2) )
  96.                 return 0;
  97.            }
  98.        }
  99.     /* Now do a type-dependent comparison. */
  100.     /* This would be very simple if we always filled in */
  101.     /* all 8 bytes of a ref, but we currently don't. */
  102.     switch ( r_btype(pref1) )
  103.        {
  104.     case t_array:
  105.         return (pref1->value.refs == pref2->value.refs &&
  106.             r_size(pref1) == r_size(pref2));
  107.     case t_mixedarray:
  108.     case t_shortarray:
  109.         return (pref1->value.packed == pref2->value.packed &&
  110.             r_size(pref1) == r_size(pref2));
  111.     case t_boolean:
  112.         return (pref1->value.index == pref2->value.index);
  113.     case t_condition:
  114.         return (pref1->value.pcond == pref2->value.pcond);
  115.     case t_dictionary:
  116.         return (pref1->value.pdict == pref2->value.pdict);
  117.     case t_file:
  118.         return (pref1->value.pfile == pref2->value.pfile);
  119.     case t_fontID:
  120.         return (pref1->value.pfont == pref2->value.pfont);
  121.     case t_gstate:
  122.         return (pref1->value.pgstate == pref2->value.pgstate);
  123.     case t_integer:
  124.         return (pref1->value.intval == pref2->value.intval);
  125.     case t_lock:
  126.         return (pref1->value.plock == pref2->value.plock);
  127.     case t_mark:
  128.     case t_null:
  129.         return 1;
  130.     case t_name:
  131.         return (pref1->value.pname == pref2->value.pname);
  132.     case t_oparray:
  133.     case t_operator:
  134.         return (op_index(pref1) == op_index(pref2));
  135.     case t_real:
  136.         return (pref1->value.realval == pref2->value.realval);
  137.     case t_save:
  138.         return (pref1->value.psave == pref2->value.psave);
  139.     case t_string:
  140.         return (!bytes_compare(pref1->value.bytes, r_size(pref1),
  141.                        pref2->value.bytes, r_size(pref2)));
  142.     case t_device:
  143.         return (pref1->value.pdevice == pref2->value.pdevice);
  144.        }
  145.     return 0;            /* shouldn't happen! */
  146. }
  147.  
  148. /* Create a printable representation of an object, a la cvs. */
  149. /* Return 0 if OK, <0 if the destination wasn't large enough. */
  150. int
  151. obj_cvs(const ref *op, byte *str, uint len, uint *prlen)
  152. {    char buf[30];            /* big enough for any float */
  153.     byte *pstr = (byte *)buf;
  154.     uint plen;
  155.     ref nref;
  156.     switch ( r_btype(op) )
  157.        {
  158.     case t_boolean:
  159.         pstr = (byte *)(op->value.index ? "true" : "false");
  160.         break;
  161.     case t_integer:
  162.         sprintf(buf, "%ld", op->value.intval);
  163.         break;
  164.     case t_name:
  165.         name_string_ref(op, &nref);    /* name string */
  166. cvname:        pstr = nref.value.bytes;
  167.         plen = r_size(&nref);
  168.         goto nl;
  169.     case t_oparray:
  170.         name_index_ref(op_array_nx_table[op_index(op) - op_def_count], &nref);
  171.         name_string_ref(&nref, &nref);
  172.         goto cvname;
  173.     case t_operator:
  174.        {    /* Recover the name from the initialization table. */
  175.         uint index = op_index(op);
  176.         if ( index != 0 )
  177.            {    pstr = (byte *)(op_def_table[index]->oname + 1);
  178.             break;
  179.            }
  180.        }
  181.         /* Internal operator, no name. */
  182.         sprintf(buf, "operator_%lx", (ulong)op->value.opproc);
  183.         break;
  184.     case t_real:
  185.         sprintf(buf, "%g", op->value.realval);
  186.         /* Make sure the output has a decimal point. */
  187.         /* This is needed for compatibility with */
  188.         /* Adobe (and other) interpreters. */
  189.         /* Old Borland compilers require &buf[0], not just buf. */
  190.         if ( strchr(&buf[0], '.') != NULL ) break;
  191.         {    char *ept = strchr(&buf[0], 'e');
  192.             if ( ept == NULL )
  193.                 strcat(buf, ".0");
  194.             else
  195.             {    /* Insert the .0 before the exponent. */
  196.                 /* What a nuisance! */
  197.                 char buf1[30];
  198.                 strcpy(&buf1[0], ept);
  199.                 strcpy(ept, ".0");
  200.                 strcat(&buf[0], &buf1[0]);
  201.             }
  202.         }
  203.         break;
  204.     case t_string:
  205.         if ( !r_has_attr(op, a_read) )
  206.             return_error(e_invalidaccess);
  207.         pstr = op->value.bytes;
  208.         plen = r_size(op);
  209.         goto nl;
  210.     default:
  211.         pstr = (byte *)"--nostringval--";
  212.        }
  213.     plen = strlen((char *)pstr);
  214. nl:    if ( plen > len )
  215.         return_error(e_rangecheck);
  216.     memcpy(str, pstr, plen);
  217.     *prlen = plen;
  218.     return 0;
  219. }
  220.  
  221. /* Find the index of an operator that doesn't have one stored in it. */
  222. ushort
  223. op_find_index(const ref *pref /* t_operator */)
  224. {    op_proc_p proc = real_opproc(pref);
  225.     register const op_def_ptr *opp = op_def_table;
  226.     register const op_def_ptr *opend = opp + op_def_count;
  227.     for ( ; ++opp < opend; )
  228.     {    if ( (*opp)->proc == proc )
  229.             return opp - op_def_table;
  230.     }
  231.     /* Lookup failed!  This isn't possible.... */
  232.     return 0;
  233. }
  234.  
  235. /* Get an element from an array of some kind. */
  236. /* This is also used to index into Encoding vectors, */
  237. /* the error name vector, etc. */
  238. int
  239. array_get(const ref *aref, long index_long, ref *pref)
  240. {    if ( (ulong)index_long >= r_size(aref) )
  241.         return_error(e_rangecheck);
  242.     switch ( r_type(aref) )
  243.        {
  244.     case t_array:
  245.        {    const ref *pvalue =
  246.            aref->value.refs + (uint)index_long;
  247.         ref_assign(pref, pvalue);
  248.        }    return 0;
  249.     case t_mixedarray:
  250.        {    const ref_packed *packed = aref->value.packed;
  251.         uint index = (uint)index_long;
  252.         for ( ; index--; ) packed = packed_next(packed);
  253.         packed_get(packed, pref);
  254.        }    return 0;
  255.     case t_shortarray:
  256.        {    const ref_packed *packed =
  257.            aref->value.packed + (uint)index_long;
  258.         packed_get(packed, pref);
  259.        }    return 0;
  260.     default:
  261.         return_error(e_typecheck);
  262.        }
  263. }
  264.  
  265. /* Check to make sure an interval contains no local object references. */
  266. /* Return 0 or e_invalidaccess. */
  267. int
  268. refs_check_global(register const ref *bot, register uint size)
  269. {    for ( ; size--; bot++ )
  270.         check_global(*bot);
  271.     return 0;
  272. }
  273.  
  274. /* ------ String utilities ------ */
  275.  
  276. /* Convert a C string to a Ghostscript string */
  277. int
  278. string_to_ref(const char *cstr, ref *pref, const char *cname)
  279. {    uint size = strlen(cstr);
  280.     char *str = alloc(size, 1, cname);
  281.     if ( str == 0 )
  282.         return_error(e_VMerror);
  283.     memcpy(str, cstr, size);
  284.     make_string(pref, a_all, size, (byte *)str);
  285.     return 0;
  286. }
  287.  
  288. /* Convert a Ghostscript string to a C string. */
  289. /* Return 0 iff the buffer can't be allocated. */
  290. char *
  291. ref_to_string(const ref *pref, const char *client_name)
  292. {    uint size = r_size(pref);
  293.     char *str = alloc(size + 1, 1, client_name);
  294.     if ( str == 0 )
  295.         return 0;
  296.     memcpy(str, (char *)pref->value.bytes, size);
  297.     str[size] = 0;
  298.     return str;
  299. }
  300.  
  301. /* ------ Operand utilities ------ */
  302.  
  303. /* Get N numeric operands from the stack. */
  304. /* Return a bit-mask indicating which ones are integers, */
  305. /* or a (negative) error indication. */
  306. /* The 1-bit in the bit-mask refers to the bottommost stack entry. */
  307. /* Store float versions of the operands at pval. */
  308. int
  309. num_params(const ref *op, int count, float *pval)
  310. {    int mask = 0;
  311.     pval += count;
  312.     while ( --count >= 0 )
  313.        {    mask <<= 1;
  314.         switch ( r_type(op) )
  315.            {
  316.         case t_real:
  317.             *--pval = op->value.realval;
  318.             break;
  319.         case t_integer:
  320.             *--pval = op->value.intval;
  321.             mask++;
  322.             break;
  323.         default:
  324.             return_error(e_typecheck);
  325.            }
  326.         op--;
  327.        }
  328.     /* If count is very large, mask might overflow. */
  329.     /* In this case we clearly don't care about the value of mask. */
  330.     return (mask < 0 ? 0 : mask);
  331. }
  332.  
  333. /* Get a real parameter. */
  334. /* If an error is returned, the return value is not updated. */
  335. int
  336. real_param(const ref *op, float *pparam)
  337. {    switch ( r_type(op) )
  338.        {
  339.     case t_integer:
  340.         *pparam = op->value.intval;
  341.         break;
  342.     case t_real:
  343.         *pparam = op->value.realval;
  344.         break;
  345.     default:
  346.         return_error(e_typecheck);
  347.        }
  348.     return 0;
  349. }
  350.  
  351. /* Make real values on the operand stack. */
  352. void
  353. make_reals(ref *op, const float *pval, int count)
  354. {    for ( ; count--; op++, pval++ )
  355.         make_real(op, *pval);
  356. }
  357.  
  358. /* Compute the error code when check_proc fails. */
  359. int
  360. check_proc_failed(const ref *pref)
  361. {    return_error((r_has_attrs(pref, a_execute + a_executable) ?
  362.               e_typecheck : e_invalidaccess));
  363. }
  364.  
  365. /* ------ Matrix utilities ------ */
  366.  
  367. /* Check for a matrix operand with read access. */
  368. /* Return 0 if OK, error code if not. */
  369. /* Store an all-float version of the matrix in *pmat. */
  370. int
  371. read_matrix(const ref *op, gs_matrix *pmat)
  372. {    switch ( r_type(op) )
  373.        {
  374.     default:
  375.         return_error(e_typecheck);
  376.     case t_array: ;
  377.        }
  378.     if ( r_size(op) != 6 )
  379.         return_error(e_rangecheck);
  380.     if ( !r_has_attr(op, a_read) )
  381.         return_error(e_invalidaccess);
  382.     *pmat = *(gs_matrix *)op->value.refs;
  383.        {    ref *pel = (ref *)pmat;
  384.         int i;
  385.         for ( i = 0; i < 6; i++ )
  386.            {    switch ( r_type(pel) )
  387.                {
  388.             default:
  389.                 return_error(e_typecheck);
  390.             case t_integer:
  391.                 make_real(pel, pel->value.intval);
  392.             case t_real: ;
  393.                }
  394.             pel++;
  395.            }
  396.        }
  397.     return 0;
  398. }
  399.  
  400. /* Check for a matrix operand with write access. */
  401. /* Return 0 if OK, error code if not. */
  402. /* Initialize the matrix to an identity matrix */
  403. /* (to set the types and attributes properly.) */
  404. int
  405. write_matrix(register ref *op)
  406. {    ref *aptr;
  407.     int i;
  408.     if ( !r_has_type(op, t_array) )
  409.         return_error(e_typecheck);
  410.     if ( !r_has_attr(op, a_write) )
  411.         return_error(e_invalidaccess);
  412.     if ( r_size(op) != 6 )
  413.         return_error(e_rangecheck);
  414.     aptr = op->value.refs;
  415.     for ( i = 5; i >= 0; i--, aptr++ )
  416.       { ref_save(aptr, "write_matrix");    /* we're going to overwrite */
  417.       }
  418.     gs_make_identity((gs_matrix *)op->value.refs);
  419.     return 0;
  420. }
  421.